package com.zxf.basic.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.viewbinding.ViewBinding
import java.util.*

/**
 * @author zjc
 * @date 2022/12/28
 */
class MultiBindingAdapter<T : MultiType>(block: MultiBindingAdapter<T>.() -> Unit): BaseAdapter<T>() {

    // 存储多种ViewBinding
    private val bindingList = arrayListOf<ViewBinding>()
    private val bindList = arrayListOf<Any>()
    private val blockList = arrayListOf<Any>()
    // 存储type种类
    private val typeList = TreeSet<Int>()
    // 空布局的回调
    private var emptyBlock: ((itemView: View) -> Unit)? = null
    private var emptyView: View? = null
    private var emptyRes = -1

    companion object {
        private const val TYPE_EMPTY = 0
    }

    override fun layout() = 0

    init {
        block.invoke(this)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        if (typeList.isEmpty()) return
        typeList.forEachIndexed { index, type ->
            if (type == getItemViewType(position)) {
                (blockList[index] as ViewBinding.(item: T, payloads: MutableList<Any>?) -> Unit).apply {
                    invoke((holder as BindingHolder<*>).binding, getData()[position], null)
                }
            }
        }
    }

    override fun onBindViewHolder(holder: Holder, position: Int, payloads: MutableList<Any>) {
        if (payloads.isEmpty()) {
            super.onBindViewHolder(holder, position, payloads)
            return
        }
        if (typeList.isEmpty()) return
        if (getItemViewType(position) == TYPE_EMPTY) {
            emptyBlock?.invoke(holder.itemView)
        }
        typeList.forEachIndexed { index, type ->
            if (type == getItemViewType(position)) {
                (blockList[index] as ViewBinding.(item: T, payloads: MutableList<Any>?) -> Unit).apply {
                    invoke((holder as BindingHolder<*>).binding, getData()[position], payloads)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        typeList.forEachIndexed { index, type ->
            if (viewType == type) {
                val binding = (bindList[index] as (layoutInflater: LayoutInflater, parent: ViewGroup, attchParent: Boolean) -> ViewBinding).invoke(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
                bindingList.add(binding)
                return BindingHolder(binding)
            }
        }
        if (viewType == TYPE_EMPTY) {
            return if (emptyRes != -1) {
                val emptyView = LayoutInflater.from(parent.context).inflate(emptyRes, parent, false)
                Holder(emptyView)
            } else if (this.emptyView != null) {
                Holder(this.emptyView!!)
            } else super.onCreateViewHolder(parent, viewType)
        }
        return super.onCreateViewHolder(parent, viewType)
    }

    fun addEmpty(@LayoutRes res: Int, block:((itemView: View) -> Unit)? = null) {
        emptyRes = res
        emptyBlock = block
    }

    fun addEmpty(emptyView: View) {
        this.emptyView = emptyView
    }

    fun <VB : ViewBinding> addType(
        initBinding: (layoutInflater: LayoutInflater, parent: ViewGroup, attchParent: Boolean) -> VB,
        block: VB.(item: T, payloads: MutableList<Any>?) -> Unit
    ) {
        bindList.add(initBinding)
        blockList.add(block)
    }

    override fun getItemViewType(position: Int): Int {
        if (getData().isEmpty()) return TYPE_EMPTY
        val type = getData()[position].getItemViewType()
        typeList.add(type)
        return type
    }

    override fun getItemCount(): Int {
        if (getData().isEmpty()) return 1
        return super.getItemCount()
    }

    inner class BindingHolder<VB : ViewBinding>(val binding: VB) : Holder(binding.root)
}